package com.fastgwt.client;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.DateCell;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.text.shared.SimpleSafeHtmlRenderer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.fastgwt.client.model.EmployeeProperties;
import com.fastgwt.shared.dto.Employee;
import com.fastgwt.shared.services.EmployeeService;
import com.fastgwt.shared.services.EmployeeServiceAsync;
import com.sencha.gxt.cell.core.client.SimpleSafeHtmlCell;
import com.sencha.gxt.cell.core.client.form.ComboBoxCell.TriggerAction;
import com.sencha.gxt.core.client.ValueProvider;
import com.sencha.gxt.core.client.util.Margins;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.data.shared.ModelKeyProvider;
import com.sencha.gxt.data.shared.StringLabelProvider;
import com.sencha.gxt.data.shared.TreeStore;
import com.sencha.gxt.examples.resources.client.TestData;
import com.sencha.gxt.examples.resources.client.images.ExampleImages;
import com.sencha.gxt.examples.resources.client.model.BaseDto;
import com.sencha.gxt.examples.resources.client.model.FolderDto;
import com.sencha.gxt.examples.resources.client.model.Stock;
import com.sencha.gxt.examples.resources.client.model.StockProperties;
import com.sencha.gxt.explorer.client.binding.BasicBindingExample;

import com.sencha.gxt.state.client.GridStateHandler;
import com.sencha.gxt.widget.core.client.ContentPanel;
import com.sencha.gxt.widget.core.client.FramedPanel;
import com.sencha.gxt.widget.core.client.Resizable;
import com.sencha.gxt.widget.core.client.Resizable.Dir;
import com.sencha.gxt.widget.core.client.box.MessageBox;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.button.ToolButton;
import com.sencha.gxt.widget.core.client.container.BorderLayoutContainer;
import com.sencha.gxt.widget.core.client.container.BorderLayoutContainer.BorderLayoutData;
import com.sencha.gxt.widget.core.client.container.MarginData;
import com.sencha.gxt.widget.core.client.container.SimpleContainer;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData;
import com.sencha.gxt.widget.core.client.container.Viewport;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.event.SelectEvent.SelectHandler;
import com.sencha.gxt.widget.core.client.form.FieldLabel;
import com.sencha.gxt.widget.core.client.form.FieldSet;
import com.sencha.gxt.widget.core.client.form.NumberField;
import com.sencha.gxt.widget.core.client.form.NumberPropertyEditor;
import com.sencha.gxt.widget.core.client.form.SimpleComboBox;
import com.sencha.gxt.widget.core.client.form.TextField;
import com.sencha.gxt.widget.core.client.form.NumberPropertyEditor.DoublePropertyEditor;
import com.sencha.gxt.widget.core.client.grid.CellSelectionModel;
import com.sencha.gxt.widget.core.client.grid.ColumnConfig;
import com.sencha.gxt.widget.core.client.grid.ColumnModel;
import com.sencha.gxt.widget.core.client.grid.Grid;
import com.sencha.gxt.widget.core.client.grid.GridSelectionModel;
import com.sencha.gxt.widget.core.client.info.Info;
import com.sencha.gxt.widget.core.client.selection.CellSelectionChangedEvent;
import com.sencha.gxt.widget.core.client.selection.CellSelectionChangedEvent.CellSelectionChangedHandler;
import com.sencha.gxt.widget.core.client.tips.QuickTip;
import com.sencha.gxt.widget.core.client.tips.ToolTipConfig;
import com.sencha.gxt.widget.core.client.toolbar.LabelToolItem;
import com.sencha.gxt.widget.core.client.toolbar.ToolBar;
import com.sencha.gxt.widget.core.client.tree.Tree;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Fastgwt implements IsWidget, EntryPoint, Editor<Employee> {
	private FramedPanel createEmployer;
	private static final StockProperties props = GWT
			.create(StockProperties.class);
	
	private static final EmployeeProperties props2 = GWT
			.create(EmployeeProperties.class);
	private ContentPanel root;
	private EmployeeServiceAsync employeeService;
	final TextField email = new TextField();
	final NumberField<Long> employeeId = new NumberField<Long>(new NumberPropertyEditor.LongPropertyEditor());
	final TextField employeeSurname = new TextField();
	final TextField employeeName = new TextField();
	 interface EmployeeDriver extends SimpleBeanEditorDriver<Employee, Fastgwt> {
	  }
	 
	  private EmployeeDriver driver = GWT.create(EmployeeDriver.class);
	 
//	  interface StockTemplate extends XTemplates {
//	    @XTemplate(source = "BasicBindingExample.html")
//	    SafeHtml drawStock(Stock stock);
//	  }

	class KeyProvider implements ModelKeyProvider<BaseDto> {
		@Override
		public String getKey(BaseDto item) {
			return (item instanceof FolderDto ? "f-" : "m-")
					+ item.getId().toString();
		}
	}

	@Override
	public Widget asWidget() {

		final BorderLayoutContainer con = new BorderLayoutContainer();
		con.setBorders(true);
		ContentPanel west = new ContentPanel();
		final ContentPanel center = new ContentPanel();
		west.setHeadingText("Menu");
		west.setPixelSize(315, 400);
		west.addStyleName("margin-10");
		center.setResize(false);

		// center.add(con);

		TreeStore<BaseDto> store = new TreeStore<BaseDto>(new KeyProvider());

		FolderDto root = TestData.getMenuRootFolder();
		for (BaseDto base : root.getChildren()) {
			store.add(base);
			if (base instanceof FolderDto) {
				processFolder(store, (FolderDto) base);
			}
		}

		SimpleSafeHtmlCell<String> cell = new SimpleSafeHtmlCell<String>(
				SimpleSafeHtmlRenderer.getInstance(), "click") {
			@Override
			public void onBrowserEvent(Context context, Element parent,
					String value, NativeEvent event,
					ValueUpdater<String> valueUpdater) {
				super.onBrowserEvent(context, parent, value, event,
						valueUpdater);
				if ("click".equals(event.getType())) {
					Info.display("Click", "You clicked \"" + value + "\"!");
				
				if (value.equals("Create Employer")) {
					if (createEmployer == null) {
						createEmployer = createForm2();
						driver.initialize(Fastgwt.this);
					}
					center.setWidget(createEmployer);
					driver.edit(new Employee());
					
					createEmployer.show();
				} else if (value.equals("List Employer")) {
					if (createEmployer != null)
						createEmployer.hide();
					center.setWidget(listEmployers());
				}
				}
			}
		};

		final Tree<BaseDto, String> tree = new Tree<BaseDto, String>(store,
				new ValueProvider<BaseDto, String>() {

					@Override
					public String getValue(BaseDto object) {
						return object.getName();
					}

					@Override
					public void setValue(BaseDto object, String value) {

					}

					@Override
					public String getPath() {
						return "name";
					}
				});
		tree.setCell(cell);
		tree.setWidth(300);
		tree.getStyle().setLeafIcon(ExampleImages.INSTANCE.form());

		ToolBar buttonBar = new ToolBar();

		buttonBar.add(new TextButton("Expand All", new SelectHandler() {

			@Override
			public void onSelect(SelectEvent event) {
				tree.expandAll();
			}
		}));
		buttonBar.add(new TextButton("Collapse All", new SelectHandler() {
			@Override
			public void onSelect(SelectEvent event) {
				tree.collapseAll();
			}

		}));

		// con.add(buttonBar, new VerticalLayoutData(1, -1));
		// con.add(tree, new VerticalLayoutData(1, 1));
		// west.add(buttonBar);
		west.add(tree);

		BorderLayoutData westData = new BorderLayoutData(150);
		westData.setCollapsible(true);
		westData.setSplit(true);
		westData.setCollapseMini(true);
		westData.setMargins(new Margins(0, 5, 0, 5));

		MarginData centerData = new MarginData();
		con.setWestWidget(west, westData);
		con.setCenterWidget(center, centerData);

		SimpleContainer simple = new SimpleContainer();
		simple.add(con, new MarginData(10));

		return simple;
	}

	private FramedPanel createForm2() {
		FramedPanel form2 = new FramedPanel();
		form2.setHeadingText("Simple Form with FieldSets");
		form2.setWidth(350);

		FieldSet fieldSet = new FieldSet();
		fieldSet.setHeadingText("User Information");
		fieldSet.setCollapsible(true);
		form2.add(fieldSet);

		VerticalLayoutContainer p = new VerticalLayoutContainer();
		fieldSet.add(p);
		
		employeeId.setAllowBlank(false);
		
		p.add(new FieldLabel(employeeId, "Employee Id"), new VerticalLayoutData(
				1, -1));

		
		
		employeeName.setAllowBlank(false);
		p.add(new FieldLabel(employeeName, "First Name"), new VerticalLayoutData(
				1, -1));

		
		employeeSurname.setAllowBlank(false);
		p.add(new FieldLabel(employeeSurname, "Last Name"), new VerticalLayoutData(1,
				-1));

		
		email.setAllowBlank(false);
		p.add(new FieldLabel(email, "Email"), new VerticalLayoutData(1, -1));

		TextButton btn = new TextButton("Save");
		btn.addSelectHandler(new SelectHandler() {
			
			@Override
			public void onSelect(SelectEvent event) {
				Employee emp = new Employee();
//				emp.setEmployeeId(Long.parseLong( idText.getText()));
//				emp.setEmployeeName(firstName.getText());
//				emp.setEmployeeSurname(lastName.getText());
//				emp.setEmail(email.getText());
				
				 driver.flush();
			        emp = driver.flush();
			        Info.display("emp",emp.toString());
			        if (driver.hasErrors()) {
			          new MessageBox("Please correct the errors before saving.").show();
			          return;
			        }
				employeeService.saveOrUpdateEmployee(emp,
						new AsyncCallback<Employee>() {
							public void onFailure(Throwable caught) {
								// Show the RPC error message to the user
								
								Info.display("failed", "rpc is failed");
							}

							public void onSuccess(Employee emp) {
								Info.display("succes", "Employee is saved name "+emp);
							}
						});
				
				
				
				
			}
		});
		form2.addButton(btn);
	
		form2.addButton(new TextButton("Cancel"));

		return form2;
	}

	public Widget listEmployers() {
		final NumberFormat number = NumberFormat.getFormat("0.00");

		ColumnConfig<Stock, String> nameCol = new ColumnConfig<Stock, String>(
				props.name(), 50, "Company");
		ColumnConfig<Stock, String> symbolCol = new ColumnConfig<Stock, String>(
				props.symbol(), 100, "Symbol");
		ColumnConfig<Stock, Double> lastCol = new ColumnConfig<Stock, Double>(
				props.last(), 75, "Last");

		ColumnConfig<Stock, Double> changeCol = new ColumnConfig<Stock, Double>(
				props.change(), 100, "Change");
		changeCol.setCell(new AbstractCell<Double>() {

			@Override
			public void render(Context context, Double value, SafeHtmlBuilder sb) {
				String style = "style='color: " + (value < 0 ? "red" : "green")
						+ "'";
				String v = number.format(value);
				sb.appendHtmlConstant("<span " + style
						+ " qtitle='Change' qtip='" + v + "'>" + v + "</span>");
			}
		});

		ColumnConfig<Stock, Date> lastTransCol = new ColumnConfig<Stock, Date>(
				props.lastTrans(), 100, "Last Updated");
		lastTransCol.setCell(new DateCell(DateTimeFormat
				.getFormat("MM/dd/yyyy")));

		List<ColumnConfig<Stock, ?>> l = new ArrayList<ColumnConfig<Stock, ?>>();
		l.add(nameCol);
		l.add(symbolCol);
		l.add(lastCol);
		l.add(changeCol);
		l.add(lastTransCol);
		ColumnModel<Stock> cm = new ColumnModel<Stock>(l);

		ListStore<Stock> store = new ListStore<Stock>(props.key());
		store.addAll(TestData.getStocks());

		root = new ContentPanel();
		root.setHeadingText("Basic Grid");
		root.getHeader().setIcon(ExampleImages.INSTANCE.table());
		root.setPixelSize(600, 300);
		root.addStyleName("margin-10");

		ToolButton info = new ToolButton(ToolButton.QUESTION);
		ToolTipConfig config = new ToolTipConfig("Example Info",
				"This examples includes resizable panel, reorderable columns and grid state.");
		config.setMaxWidth(225);
		info.setToolTipConfig(config);
		root.addTool(info);

		Resizable r = new Resizable(root, Dir.E, Dir.SE, Dir.S);
		r.setMinHeight(200);
		r.setMinWidth(300);

		final Grid<Stock> grid = new Grid<Stock>(store, cm);
		grid.getView().setAutoExpandColumn(nameCol);
		grid.getView().setStripeRows(true);
		grid.getView().setColumnLines(true);
		grid.setBorders(false);

		grid.setColumnReordering(true);
		grid.setStateful(true);
		grid.setStateId("gridExample");

		GridStateHandler<Stock> state = new GridStateHandler<Stock>(grid);
		state.loadState();

		ToolBar toolBar = new ToolBar();
		toolBar.add(new LabelToolItem("Selection Mode: "));

		SimpleComboBox<String> type = new SimpleComboBox<String>(
				new StringLabelProvider<String>());
		type.setTriggerAction(TriggerAction.ALL);
		type.setEditable(false);
		type.setWidth(100);
		type.add("Row");
		type.add("Cell");
		type.setValue("Row");
		// we want to change selection model on select, not value change which
		// fires on blur
		type.addSelectionHandler(new SelectionHandler<String>() {

			@Override
			public void onSelection(SelectionEvent<String> event) {
				boolean cell = event.getSelectedItem().equals("Cell");
				if (cell) {
					CellSelectionModel<Stock> c = new CellSelectionModel<Stock>();
					c.addCellSelectionChangedHandler(new CellSelectionChangedHandler<Stock>() {

						@Override
						public void onCellSelectionChanged(
								CellSelectionChangedEvent<Stock> event) {

						}
					});

					grid.setSelectionModel(c);
				} else {
					grid.setSelectionModel(new GridSelectionModel<Stock>());
				}
			}
		});
		type.addValueChangeHandler(new ValueChangeHandler<String>() {

			@Override
			public void onValueChange(ValueChangeEvent<String> event) {

			}
		});
		toolBar.add(type);

		VerticalLayoutContainer con = new VerticalLayoutContainer();
		root.setWidget(con);

		con.add(toolBar, new VerticalLayoutData(1, -1));
		con.add(grid, new VerticalLayoutData(1, 1));

		// needed to enable quicktips (qtitle for the heading and qtip for the
		// content) that are setup in the change GridCellRenderer
		new QuickTip(grid);

		return root;
	}

	public void onModuleLoad() {
		// RootPanel.get().add(asWidget());
		employeeService = (EmployeeServiceAsync) GWT
				.create(EmployeeService.class);

		Widget con = asWidget();
		Viewport viewport = new Viewport();
		viewport.add(con);
		RootPanel.get().add(viewport);
	}

	private void processFolder(TreeStore<BaseDto> store, FolderDto folder) {
		for (BaseDto child : folder.getChildren()) {
			store.add(folder, child);
			if (child instanceof FolderDto) {
				processFolder(store, (FolderDto) child);
			}
		}
	}
}
